
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
from threading import Thread
import serial
import time
from scipy.fftpack import fft
from scipy.signal import get_window
x_time=[]#横坐标时间
y_ad=[]#纵坐标
re_status=True
pic_status=True
matplotlib.rcParams['font.sans-serif'] = ['KaiTi']#解决汉字显示
matplotlib.rcParams['axes.unicode_minus']=False#解决负号显示
def t_receive(com:serial.Serial,maxlongth:int=1000):#多线程接收函数，用以监听串口并更新数据.longth储存的最大数据量
    global x_time,y_ad,re_status
    while re_status:
        if com.in_waiting:
            try:
                text=com.readline().decode("utf-8",errors="ignore")
                text=text.split(",")
                x_n=round(int(text[0])/100000,5)
                y_n=round(int(text[1])*3.3/4096,2)
                if len(x_time)!=0:#数据检查函数
                    if abs(x_n-x_time[-1])>2:
                        print("error")
                        continue
            except Exception as e:
                print("数据格式错误",e)
                continue
            print("(%.5f,%.2f)"%(x_n,y_n))
            y_ad.append(y_n)
            x_time.append(x_n)
            while len(y_ad)>maxlongth:
                del x_time[0],y_ad[0]
    x_time.clear()
    y_ad.clear()

def draw_static(x_time,y_ad):#绘制静态曲线图，加窗并FFT
    N=len(x_time)#采样点数
    n=1/(x_time[1]-x_time[0])#采样率
    x=np.array(x_time)
    y=np.array(y_ad)
    x_fft=np.arange(N)*(n/N)#fft的频率分辨率是采样频率除以采样点数
    y_fft=fft(get_window("cosine",N)*y)#加窗并fft
    #y_fft=fft(y)
    y_fft=np.abs(y_fft)#取模，得到振幅谱
    y_fft=y_fft/(N/2)#归一化处理
    y_fft[0]/=2
    x_fft=x_fft[range(int(N/2))]
    y_fft=y_fft[range(int(N/2))]#取半
    plt.figure()
    plt.subplot(121)
    plt.title("信号图像")
    plt.plot(x,y)
    plt.subplot(122)
    plt.title("频域信号")
    plt.plot(x_fft,y_fft)
    plt.show()
def draw_active(x_time,y_ad):#绘制动态图像，出现类示波器效果
    global pic_status
    plt.ion()
    while pic_status:
        plt.cla()
        plt.plot(x_time,y_ad)
        plt.pause(0.1)
    plt.ioff()
    plt.close()
def setdraw(status):
    global pic_status
    pic_status=status
def start_draw(com:serial.Serial):#开始接收数据
    global re_status,x_time,y_ad
    print("开始监听串口")
    re=Thread(target=t_receive,args=(com,))
    re.start()
    time.sleep(5)
    ft=1
    while ft!="q":
        ft=input("选择功能\n1----FFT\n2----示波器\nq----退出你的选择:")
        if ft=="1":
            draw_static(x_time,y_ad)
            continue
        elif ft=="2":
            draw_active(x_time,y_ad)
            continue
        else:
            continue
    re_status=False
    re.join()
if __name__=="__main__":
    com=serial.Serial("COM4",baudrate=115200)
    start_draw(com)
